layui.define(['toast', 'api', 'storage', 'http'], function (exports) {

    let api = layui.api;
    let http = layui.http;
    let toast = layui.toast;
    let storage = layui.storage;
    let laydate = layui.laydate;

    const table = (config) => {

        let table = layui.table;
        let form = layui.form;
        let urls = config.route || {};

        let columns = config.columns || [];
        let right_toolbars = config.right_toolbars || [];
        let photos = [];

        try {
            for (let i in columns) {
                let column = columns[i];
                let template = column.templet;
                if (template === 'image') {
                    column.templet = function (d) {
                        let column = d.LAY_COL.field || '';
                        let title = d.LAY_COL.title || '';
                        let src = d[column];
                        if (!src) {
                            return '';
                        }
                        let index = photos.length;
                        if (Array.isArray(src)) {
                            let s = '';
                            for (let i in src) {
                                s += `<img class="page-table-img" data-index="${index}" layer-src="${src[i]}" src=" ${src[i]} ">`;
                                photos.push({
                                    'alt': title + ' : ' + (photos.length + 1),
                                    'pid': photos.length + 1,
                                    'src': src[i],
                                });
                            }
                            return s;
                        } else {
                            photos.push({
                                'alt': title + ' : ' + (photos.length + 1),
                                'pid': photos.length + 1,
                                'src': src,
                            });
                            return `<img class="page-table-img" data-index="${index}" src="${src}">`;
                        }
                    };
                } else if (template === 'switch') {
                    let extra = column.extra || {};
                    column.templet = function (d) {
                        let column = d.LAY_COL.field || '';
                        let id = parseInt(d['id']);
                        let value = parseInt(d[column]);
                        let checked = '';
                        if (value) {
                            checked = 'checked';
                        }
                        let show_text = extra.show_text || '开启|关闭';

                        return `<div><input type="checkbox" lay-skin="switch" data-value="${value}" data-field="${column}" data-id="${id}" lay-filter="table-switch" title="${show_text}" ${checked}></div>`;
                    };
                } else if (template === 'icon') {
                    column.templet = function (d) {
                        let column = d.LAY_COL.field || '';
                        let value = d[column];
                        if (value) {
                            value = '<i class="' + value + '"></i>';
                        }
                        return value;
                    };
                } else if (template === 'action') {
                    column.templet = function (d) {
                        let extra = d.LAY_COL.extra || {};
                        let container = '';
                        for (let i in extra) {
                            let btn = extra[i];
                            // 去一个随机数,用于绑定表格中每列的事件,用于区分是哪一行
                            let event = generate_random_str(8);
                            let map = base64_to_json(btn.map);
                            if (Object.keys(map).length) {
                                for (let m in map) {
                                    map[m] = d[map[m]];
                                    event += generate_random_str(8) + '-' + map[m];
                                }
                                map = json_to_base64(map);
                            } else {
                                map = '';
                            }
                            container += `
                  <a class="layui-btn ${btn.style} layui-btn-xs"
                   lay-event="${event}"
                   data-url="${btn.url}"
                   data-text="${btn.text}"
                   data-target="${btn.target}"
                   data-dialog="${btn.dialog}"
                   data-confirm="${btn.confirm}"
                   data-query="${btn.query}"
                   data-map="${map}"
                   >${btn.text}</a>
                  `;
                        }
                        return '<div class="layui-clear-space">' + container + '</div>';
                    };
                }
            }
        } catch (e) {

        }

        const dispatch = (event) => {

            let _this = $('[lay-event=' + event + ']')

            let url = _this.data('url') || '';
            let dialog = base64_to_json(_this.data('dialog'));
            let confirm = base64_to_json(_this.data('confirm'));
            let query = _this.data('query');
            let map = base64_to_json(_this.data('map'));

            let params = {};
            if (query && typeof query === 'object') {
                params = Object.assign({}, query)
            }

            if (map && typeof map === 'object') {
                params = Object.assign({}, map)
            }

            switch (event) {
                case '__reload__':
                    table.reload('page-table-render', {}, true);
                    break;
                case '__redirect__':
                    if (config) {

                        if (query) {
                            for (let i in query) {
                                url += i + '=' + query[i] + '&';
                            }
                        }
                        let target = config.target || '_blank';

                        let redirect = function () {
                            if (target === '_blank') {
                                window.open(url);
                            } else {
                                window.location.href = url;
                            }
                        };

                        if (Object.keys(confirm).length) {
                            let confirm_index = layer.confirm(confirm.content, {
                                title: confirm.title,
                                icon: confirm.icon,
                                zIndex: 29891014
                            }, function () {
                                layer.close(confirm_index);
                                redirect();
                            });
                        } else {
                            redirect();
                        }
                    }
                    break;
                default :

                    let post = function () {
                        let loading = layer.open({
                            type: 3,
                            icon: 2,
                            shade: 0.4,
                            zIndex: 29891014,
                        });

                        try {
                            api.post(url, params, dialog)
                            layer.close(loading);
                        } catch (e) {
                            console.log('ajax error', e);
                        }
                    };

                    if (Object.keys(confirm).length) {
                        let confirm_index = layer.confirm(confirm.content, {
                            title: confirm.title,
                            icon: confirm.icon,
                            zIndex: 29891014,
                            offset: '150px'
                        }, function () {
                            layer.close(confirm_index);
                            post();
                        });
                    } else {
                        post();
                    }

                    break;
            }
        };

        let options = table_common_options(urls.index || '');
        options.toolbar = '#toolbar';
        options.defaultToolbar = right_toolbars;
        options.cellMinWidth = 100;
        options.height = 'full-150';
        options.before = function (options) {
            options.where = form.val('table-query');
        };
        options.cols = [columns];
        table.render(options);

        // 绑定工具栏事件
        table.on('toolbar(page-table-render)', function (obj) {
            let event = obj.event;
            dispatch(event);
        });

        // 表格列的事件
        table.on('tool(page-table-render)', function (obj) {
            let event = obj.event;
            dispatch(event);
        });

        table.on('edit(page-table-render)', function (obj) {
            let field = obj.field;
            let value = obj.value;
            let data = obj.data;
            http.post(urls.patch || '', {
                id: data.id || '',
                field: field,
                value: value,
            }).then(res => {
                toast.top(res)
            });
        });

        form.on('switch(table-switch)', function (data) {
            let elem = data.elem;
            let checked = elem.checked;

            let id = $(elem).data('id');
            let field = $(elem).data('field');
            let value = checked ? 1 : 0;

            if (id) {
                http.post(urls.patch || '', {
                    id: id,
                    field: field,
                    value: value,
                }).then(res => {
                    toast.top(res)
                });
            }
        });

        $('[data-date]').each(function () {
            let id = $(this).attr('id');
            let type = $(this).data('format');
            let range = $(this).data('range');
            laydate.render({
                elem: '#' + id,
                type: type,
                range: range ? '~' : false,
                rangeLinked: range ? true : false,
                calendar: true,
                theme: '#1e9fff'
            });
        });

        $('[lay-id=page-table]').on('click', '.page-table-img', function (event) {
            event.stopPropagation();
            let index = $(this).data('index');
            layer.photos({
                photos: {
                    'title': '图片查看器',
                    'start': index,
                    'data': photos,
                },
            });
            return false;
        });

        form.on('submit(search)', function (data) {
            table.reloadData('page-table-render', {
                where: data.field,
            });
            return false;
        });

    };

    const form = (config) => {

        let laytpl = layui.laytpl;
        let upload = layui.upload;
        let form = layui.form;
        let stay_on_the_page = false;

        let template = $('#thumbnail').html();

        $('[data-upload]').each(function () {

            let id = $(this).attr('id');
            let name = $(this).data('name');
            let limit = $(this).data('limit');
            let size = $(this).data('size');
            let ext = $(this).data('ext');
            let accept = $(this).data('accept');
            let multiple = $(this).data('multiple');
            let url = $(this).data('url');
            let disk = $(this).data('disk');
            //创建一个上传组件
            upload.render({
                elem: '#' + id,
                url: url,
                field: name,
                size: size,
                number: limit,
                exts: ext,
                accept: accept,
                multiple: multiple,
                auto: false,
                data: {
                    name: name,
                    disk: disk,
                },
                choose: function (obj) {
                    let len = $('#upload_thumb_water_pic_' + name).find('li').length;
                    let files = obj.pushFile();
                    obj.preview(function (index, file, result) {
                        if (len >= limit) {
                            toast.top(lang.upload.maximize || '选择的数量超出允许的数量');
                            delete files[index];
                        } else {
                            obj.upload(index, file);
                        }
                    });
                },
                done: function (res, index, upload) {
                    if (res.code) {
                        toast.center(res.msg);
                    } else {
                        appendLi(name, res.data);
                    }
                },
            });
        });

        // 渲染文件数据
        $('[data-upload-values]').each(function () {
            let values = $(this).data('upload-values');
            let name = $(this).data('name');
            values = values.split(',');
            if (values) {
                for (let i in values) {
                    let value = values[i];
                    if (value) {
                        appendLi(name, {'url': value});
                    }
                }
            }
        });

        function appendLi(name, data) {
            let li = laytpl(template, {
                open: '<%',
                close: '%>'
            }).render(data);
            $('#upload_thumb_water_pic_' + name).append(li);
        }

        $('.plupload-preview').on('click', '.remove-picture', function () {
            $(this).parents('li').remove();
        });

        // 上传文件从附件中选择
        $('[data-choose-attachment]').on('click', function () {
            let limit = parseInt($(this).data('limit'));
            let ext = $(this).data('ext');
            let name = $(this).data('name');
            let choose_name = 'attachment_choose_items';
            if (isNaN(limit) || limit <= 0) {
                limit = 1;
            }

            let width = $(window).width();
            let height = $(window).height();
            
            width = parseInt(width * 0.9);
            height = parseInt(height * 0.9);

            storage.remove(choose_name);
            layer.open({
                title: lang.attachment.list || '附件列表',
                type: 2,
                content: '/admin/attachment/choose?limit=' + limit + '&ext=' + ext,
                area: [width + 'px', height + 'px'],
                btn: [lang.btn.ok || '确定', lang.btn.close || '关闭'],
                yes: function (index) {
                    let choose = storage.get(choose_name);
                    if (choose && Array.isArray(choose)) {
                        if (choose.length > limit) {
                            toast.top(lang.upload.maximize || '选择的数量超出允许的数量');
                            return false;
                        }

                        let len = $('#upload_thumb_water_pic_' + name).find('li').length;
                        if (len >= limit) {
                            toast.top(lang.upload.maximize || '选择的数量超出允许的数量');
                            return false;
                        }

                        for (let i in choose) {
                            appendLi(name, {'url': choose[i]});
                        }
                        layer.close(index);
                    }
                },
                end: function () {
                    storage.remove(choose_name);
                },
            });
        });

        form.on('checkbox(stay-on-the-page)', function (data) {
            let elem = data.elem;
            let checked = elem.checked;
            if (checked) {
                stay_on_the_page = true;
            } else {
                stay_on_the_page = false;
            }
        });

        //监听提交
        form.on('submit(form-submit)', function (data) {
            let action = $('#form').attr('action');
            let params = data.field;
            // 处理文件数据
            $('.plupload-preview').each(function () {
                let name = $(this).data('name');
                let limit = parseInt($(this).data('limit'));
                if (limit === 1) {
                    params[name] = $(this).find('li [data-path]:first').data('path');
                } else if (limit > 1) {
                    let path = [];
                    $(this).find('li [data-path]').each(function () {
                        path.push($(this).data('path'));
                    });
                    params[name] = path;
                }
            });

            /**
             * 处理checkbox数据
             * 这里使用的data-type=checkbox识别是不是复选框，原因是layui的switch的类型也是checkbox
             * 且value值是用来转化是否选择的判断条件，value=1 是用0、1表，默认是on off
             */
            $('form input[data-type=checkbox]').each(function () {
                let name = $(this).attr('name');
                if (!Array.isArray(params[name])) {
                    params[name] = [];
                }
                if ($(this).prop('checked')) {
                    params[name].push($(this).data('value'));
                }
            });

            // 处理switch数据
            $('form [data-type=switch]').each(function () {
                let name = $(this).attr('name');
                if ($(this).prop('checked')) {
                    params[name] = 1;
                } else {
                    params[name] = 0;
                }
            });

            api.post(action, params).then(res => {

                try {
                    let table = layui.table;
                    table.reload('page-table-render', {}, true);
                } catch (e) {

                }

                toast.response(res, '');

                if (!res.code) {
                    if (stay_on_the_page === false) {
                        setTimeout(function () {
                            layer.closeAll();
                        }, 2000);
                    }
                }
            });
            return false;
        });

        $('#form-reset').on('click', function () {
            let index = layer.confirm((lang.dialog.form_reset || '') + '<br>' + (lang.dialog.form_reset_tip || ''), {
                icon: 3,
                title: lang.dialog.miss_tips || '',
                offset: '150px',
                btn: [lang.btn.ok || '', lang.btn.close || '']
            }, function () {
                $('form input,textarea').val('');
                layer.close(index);
            });
            return false;
        });

        $('[data-date]').each(function () {
            let id = $(this).attr('id');
            let type = $(this).data('format');
            let range = $(this).data('range');
            laydate.render({
                elem: '#' + id,
                type: type,
                range: range ? '~' : false,
                calendar: true,
                theme: '#1e9fff'
            });
        });

        if (typeof tinymce === 'object') {
            let editor_config = config['editor'] || {};
            $('[textarea-fetch-rich]').each(function () {
                let id = $(this).attr('id');
                let url = $(this).data('url');
                let readonly = $(this).attr('readonly');
                tinymce.init({
                    selector: '#' + id, //调用放在langs文件夹内的语言包
                    language: 'zh-Hans', // 取消显示升级按钮
                    promotion: false, // 取消右下角的水印
                    branding: false,
                    plugins: editor_config.plugins || '', //编辑器高度
                    height: 650,
                    min_height: 400,
                    readonly: readonly === 'readonly',
                    setup: function (editor) {
                        editor.on('change', function () {
                            editor.save();
                        });
                    },
                    images_upload_handler: (info, progress) => new Promise((resolve, reject) => {
                        let xhr, formData;
                        let file = info.blob();
                        xhr = new XMLHttpRequest();
                        xhr.withCredentials = false;
                        xhr.open('POST', url);
                        xhr.onload = function () {
                            if (xhr.status !== 200) {
                                reject(('Server Error: ') + xhr.status);
                                return;
                            }
                            let json = JSON.parse(xhr.responseText);
                            if (typeof json !== 'object') {
                                reject(lang.tinymce.format || '返回格式错误');
                            }
                            if (json.code) {
                                reject(json.msg);
                                return;
                            }
                            resolve(json.data.url);
                        };
                        formData = new FormData();
                        formData.append('file', file, file.name);
                        xhr.send(formData);
                    }),
                });
            });
        }
    };

    exports('page', {
        table: table,
        form: form,
    });
});